home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcl
/
docs.lha
/
cmu-user
/
cmu-user.info-2
< prev
next >
Wrap
Text File
|
1992-08-05
|
53KB
|
1,471 lines
Info file: cmu-user.info, -*-Text-*-
produced by latexinfo-format-buffer
from file: cmu-user.tex
File: cmu-user.info Node: The Reader, Prev: Load, Up: Design Choices and Extensions, Next: Running Programs from Lisp
The Reader
==========
-- Variable: *ignore-extra-close-parentheses*
If this variable is true (the default), then the reader merely prints a
warning when an extra close parenthesis is detected (instead of signalling an
error.)
File: cmu-user.info Node: Running Programs from Lisp, Prev: The Reader, Up: Design Choices and Extensions, Next: Saving a Core Image
Running Programs from Lisp
==========================
It is possible to run programs from Lisp by using the following
function.
-- Function: run-program
PROGRAM ARGS
&keys :env :wait :pty :input
:if-input-does-not-exist
:output ...
`Run-program' runs PROGRAM in a child process. PROGRAM should be a
pathname or string naming the program. ARGS should be a list of
strings which this passes to PROGRAM as normal Unix parameters.
For no arguments, specify ARGS as nil. The value returned is
either a process structure or nil. The process interface follows
the description of `run-program'. If `run-program' fails to fork
the child process, it returns nil.
Except for sharing file descriptors as explained in keyword
argument descriptions, `run-program' closes all file descriptors in
the child process before running the program. When you are done
using a process, call `process-close' to reclaim system resources.
You only need to do this when you supply :stream for one of :input,
:output, or :error, or you supply :pty non-nil. You can call
`process-close' regardless of whether you must to reclaim resources
without penalty if you feel safer.
`run-program' accepts the following keyword arguments:
:env
This is an a-list mapping keywords and simple-strings. The
default is `ext:*environment-list*'. If :env is specified,
`run-program' uses the value given and does not combine the
environment passed to Lisp with the one specified.
:wait
If non-nil (the default), wait until the child process
terminates. If nil, continue running Lisp while the child
process runs.
:pty
This should be one of true, nil, or a stream. If specified
non-nil, the subprocess executes under a Unix PTY. If
specified as a stream, the system collects all output to this
pty and writes it to this stream. If specified as true, the
`process-pty' slot contains a stream from which you can read
the program's output and to which you can write input for the
program. The default is nil.
:input
This specifies how the program gets its input. If specified
as a string, it is the name of a file that contains input for
the child process. `run-program' opens the file as standard
input. If specified as nil (the default), then standard input
is the file `/dev/null'. If specified as true, the program
uses the current standard input. This may cause some
confusion if :wait is nil since two processes may use the
terminal at the same time. If specified as :stream, then the
`process-input' slot contains an output stream. Anything
written to this stream goes to the program as input. :Input
may also be an input stream that already contains all the
input for the process. In this case `run-program' reads all
the input from this stream before returning, so this cannot be
used to interact with the process.
:if-input-does-not-exist
This specifies what to do if the input file does not exist.
The following values are valid: nil (the default) causes
`run-program' to return nil without doing anything; :create
creates the named file; and :error signals an error.
:output
This specifies what happens with the program's output. If
specified as a pathname, it is the name of a file that
contains output the program writes to its standard output. If
specified as nil (the default), all output goes to
`/dev/null'. If specified as true, the program writes to the
Lisp process's standard output. This may cause confusion if
:wait is nil since two processes may write to the terminal at
the same time. If specified as :stream, then the
`process-output' slot contains an input stream from which you
can read the program's output.
:if-output-exists
This specifies what to do if the output file already exists.
The following values are valid: nil causes `run-program' to
return nil without doing anything; :error (the default)
signals an error; :supersede overwrites the current file; and
:append appends all output to the file.
:error
This is similar to :output, except the file becomes the
program's standard error. Additionally, :error can be :output
in which case the program's error output is routed to the same
place specified for :output. If specified as :stream, the
`process-error' contains a stream similar to the
`process-output' slot when specifying the :output argument.
:if-error-exists
This specifies what to do if the error output file already
exists. It accepts the same values as :if-output-exists.
:status-hook
This specifies a function to call whenever the process changes
status. This is especially useful when specifying :wait as
nil. The function takes the process as a required argument.
:before-execve
This specifies a function to run in the child process before
it becomes the program to run. This is useful for actions
such as authenticating the child process without modifying the
parent Lisp process.
* Menu:
* Process Accessors::
File: cmu-user.info Node: Process Accessors, Prev: Running Programs from Lisp, Up: Running Programs from Lisp
Process Accessors
-----------------
The following functions interface the process returned by `run-program':
-- Function: process-p THING
This function returns true if THING is a process. Otherwise it returns
nil
-- Function: process-pid PROCESS
This function returns the process ID, an integer, for the PROCESS.
-- Function: process-status PROCESS
This function returns the current status of PROCESS, which is one
of `:running', `:stopped', `:exited', or `:signaled'.
-- Function: process-exit-code PROCESS
This function returns either the exit code for PROCESS, if it is
`:exited', or the termination signal PROCESS if it is `:signaled'.
The result is undefined for processes that are still alive.
-- Function: process-core-dumped PROCESS
This function returns true if someone used a Unix signal to
terminate the PROCESS and caused it to dump a Unix core image.
-- Function: process-pty PROCESS
This function returns either the two-way stream connected to
PROCESS's Unix PTY connection or nil if there is none.
-- Function: process-input PROCESS
-- Function: process-output PROCESS
-- Function: process-error PROCESS
If the corresponding stream was created, these functions return the
input, output or error file descriptor. nil is returned if there
is no stream.
-- Function: process-status-hook PROCESS
This function returns the current function to call whenever
PROCESS's status changes. This function takes the PROCESS as a
required argument. `process-status-hook' is `setf''able.
-- Function: process-plist PROCESS
This function returns annotations supplied by users, and it is
`setf''able. This is available solely for users to associate
information with PROCESS without having to build a-lists or hash
tables of process structures.
-- Function: process-wait
PROCESS &optional CHECK-FOR-STOPPED
This function waits for PROCESS to finish. If CHECK-FOR-STOPPED is
non-nil, this also returns when PROCESS stops.
-- Function: process-kill
process signal &optional WHOM
This function sends the Unix SIGNAL to PROCESS. SIGNAL should be
the number of the signal or a keyword with the Unix name (for example,
:sigsegv). WHOM should be one of the following:
:pid
This is the default, and it indicates sending the signal to
PROCESS only.
:process-group
This indicates sending the signal to PROCESS's group.
:pty-process-group
This indicates sending the signal to the process group
currently in the foreground on the Unix PTY connected to
PROCESS. This last option is useful if the running program is
a shell, and you wish to signal the program running under the
shell, not the shell itself. If `process-pty' of PROCESS is
nil, using this option is an error.
-- Function: process-alive-p PROCESS
This function returns true if PROCESS's status is either `:running'
or `:stopped'.
-- Function: process-close PROCESS
This function closes all the streams associated with PROCESS. When
you are done using a process, call this to reclaim system
resources.
File: cmu-user.info Node: Saving a Core Image, Prev: Running Programs from Lisp, Up: Design Choices and Extensions, Next: Search Lists
Saving a Core Image
===================
A mechanism has been provided to save a running Lisp core image and to
later restore it. This is convenient if you don't want to load several
files into a Lisp when you first start it up. The main problem is the
large size of each saved Lisp image, typically at least 20 megabytes.
-- Function: save-lisp
FILE
&keys :purify :root-structures :init-function
:load-init-file :print-herald
:process-command-line
The `save-lisp' function saves the state of the currently running Lisp
core image in FILE. The keyword arguments have the following meaning:
:purify
If non-NIL (the default), the core image is purified before it
is saved. This means moving accessible Lisp objects from
dynamic space into read-only and static space. This reduces
the amount of work the garbage collector must do when the
resulting core image is being run. Also, if more than one
Lisp is running on the same machine, this maximizes the amount
of memory that can be shared between the two processes.
Objects in read-only and static space can never be reclaimed,
even if all pointers to them are dropped.
:root-structures
This should be a list of the main entry points for the
resulting core image. The purification process tries to
localize symbols, functions, etc., in the core image so that
paging performance is improved. The default value is NIL
which means that Lisp objects will still be localized but
probably not as optimally as they could be. This argument has
no meaning if :purify is NIL.
:init-function
This is a function which is called when the saved core is
resumed. The default function simply aborts to the top-level
read-eval-print loop. If the function returns, it will be the
value of `save-lisp'.
:load-init-file
If non-NIL, then load an init file; either the one specified
on the command line or "`init.'FASL-TYPE", or, if
"`init.'FASL-TYPE" does not exist, `init.lisp' from the user's
home directory. If the init file is found, it is loaded into
the resumed core file before the read-eval-print loop is
entered.
:print-herald
If non-NIL, then print out the standard Lisp herald when
starting.
:process-command-line
If non-NIL, processes the command line switches and performs
the appropriate actions.
To resume a saved file, type:
lisp -core file
File: cmu-user.info Node: Search Lists, Prev: Saving a Core Image, Up: Design Choices and Extensions, Next: Time Parsing and Formatting
Search Lists
============
Search lists are an extension to Common Lisp pathnames. Search lists are used
for two purposes:
* They provide a convenient shorthand for commonly used directory names,
and
* They allow the abstract (directory structure independent) specification
of file locations in program pathname constants (similar to logical pathnames.)
Each search list has an associated list of directories (represented as
pathnames with no name or type component.) The namestring for any
relative pathname may be prefixed with "SLIST`:'", indicating that the
pathname is relative to the search list SLIST (instead of to the current
working directory.) Once qualified with a search list, the pathname is
no longer considered to be relative.
When a search list qualified pathname is passed to a file-system
operation such as `open', `load' or `truename', each directory in the
search list is successively used as the root of the pathname until the
file is located. When a file is written to a search list directory, the
file is always written to the first directory in the list.
-- Function: search-list NAME
This function returns the list of directories associated with the
search list NAME. If NAME is not a defined search list, then an
error is signalled. When set with `setf', the list of directories
is changed to the new value. If the new value is just a namestring
or pathname, then it is interpreted as a one-element list. Note
that (unlike Unix pathnames), search list names are
case-insensitive.
-- Function: search-list-defined-p NAME
-- Function: clear-search-list NAME
`search-list-defined-p' returns true if NAME is a defined search
list name, false otherwise. `clear-search-list' make the search
list NAME undefined.
-- Macro: enumerate-search-list
(VAR PATHNAME [result])
{form}*
This macro provides an interface to search list resolution. The
body FORMS are executed with VAR bound to each successive possible
expansion for NAME. If NAME does not contain a search-list, then
the body is executed exactly once. Everything is wrapped in a
block named nil, so `return' can be used to terminate early. The
RESULT form (default nil) is evaluated to determine the result of
the iteration.
* Menu:
* Search List Example::
File: cmu-user.info Node: Search List Example, Prev: Search Lists, Up: Search Lists
Search List Example
-------------------
The search list `code:' can be defined as follows:
(setf (ext:search-list "code:") '("/usr/lisp/code/"))
It is now possible to use `code:' as an abbreviation for the directory
`/usr/lisp/code/' in all file operations. For example, you can now
specify `code:eval.lisp' to refer to the file
`/usr/lisp/code/eval.lisp'.
To obtain the value of a search-list name, use the function search-list
as follows:
(ext:search-list NAME)
Where NAME is the name of a search list as described above. For example,
calling `ext:search-list' on `code:' as follows:
(ext:search-list "code:")
returns the list `("/usr/lisp/code/")'.
File: cmu-user.info Node: Time Parsing and Formatting, Prev: Search Lists, Up: Design Choices and Extensions, Next: Lisp Library
Time Parsing and Formatting
===========================
Functions are provided to allow parsing strings containing time
information and printing time in various formats are available.
-- Function: parse-time
TIME-STRING
&keys :error-on-mismatch :default-seconds
:default-minutes :default-hours
:default-day ...
`parse-time' accepts a string containing a time (e.g.,
"`Jan 12, 1952'")
and returns the universal time if it is successful. If it is unsuccessful
and the keyword argument :error-on-mismatch is non-false, it signals an
error. Otherwise it returns false. The other keyword arguments have the
following meaning:
:default-seconds
specifies the default value for the seconds value if one is
not provided by TIME-STRING. The default value is 0.
:default-minutes
specifies the default value for the minutes value if one is
not provided by TIME-STRING. The default value is 0.
:default-hours
specifies the default value for the hours value if one is not
provided by TIME-STRING. The default value is 0.
:default-day
specifies the default value for the day value if one is not
provided by TIME-STRING. The default value is the current
day.
:default-month
specifies the default value for the month value if one is not
provided by TIME-STRING. The default value is the current
month.
:default-year
specifies the default value for the year value if one is not
provided by TIME-STRING. The default value is the current
year.
:default-zone
specifies the default value for the time zone value if one is
not provided by TIME-STRING. The default value is the current
time zone.
:default-weekday
specifies the default value for the day of the week if one is
not provided by TIME-STRING. The default value is the current
day of the week.
Any of the above keywords can be given the value :current which
means to use the current value as determined by a call to the
operating system.
-- Function: format-universal-time
dest universal-time
&keys :timezone
:style :date-first
:print-seconds ...
-- Function: format-decoded-time
dest seconds minutes hours day month year &key ...
`format-universal-time' formats the time specified by UNIVERSAL-TIME.
`format-decoded-time' formats the time specified by SECONDS,
MINUTES, HOURS, DAY, MONTH, and YEAR.
DEST is any destination accepted by the `format' function.
The keyword arguments have the following meaning:
:timezone
is an integer specifying the hours west of Greenwich.
:Timezone defaults to the current time zone.
:style
specifies the style to use in formatting the time. The legal
values are:
:short
specifies to use a numeric date.
:long
specifies to format months and weekdays as words instead
of numbers.
:abbreviated
is similar to long except the words are abbreviated.
:government
is similar to abbreviated, except the date is of the form
"day month year" instead of "month day, year".
:date-first
if non-false (default) will place the date first. Otherwise,
the time is placed first.
:print-seconds
if non-false (default) will format the seconds as part of the
time. Otherwise, the seconds will be omitted.
:print-meridian
if non-false (default) will format "AM" or "PM" as part of the
time. Otherwise, the "AM" or "PM" will be omitted.
:print-timezone
if non-false (default) will format the time zone as part of
the time. Otherwise, the time zone will be omitted.
:print-seconds
if non-false (default) will format the seconds as part of the
time. Otherwise, the seconds will be omitted.
:print-weekday
if non-false (default) will format the weekday as part of
date. Otherwise, the weekday will be omitted.
File: cmu-user.info Node: Lisp Library, Prev: Time Parsing and Formatting, Up: Design Choices and Extensions
Lisp Library
============
The CMU Common Lisp project maintains a collection of useful or interesting
programs written by users of our system. The library is in
`lib/contrib/'. Two files there that users should read are:
CATALOG.TXT
This file contains a page for each entry in the library. It
contains information such as the author, portability or dependency
issues, how to load the entry, etc.
READ-ME.TXT
This file describes the library's organization and all the possible
pieces of information an entry's catalog description could contain.
Hemlock has a command Library Entry that displays a list of the current
library entries in an editor buffer. There are mode specific commands
that display catalog descriptions and load entries. This is a simple
and convenient way to browse the library.
File: cmu-user.info Node: The Debugger, Prev: Design Choices and Extensions, Up: Top, Next: The Compiler
The Debugger
************
By Robert MacLachlan
* Menu:
* Debugger Introduction::
* The Command Loop::
* Stack Frames::
* Variable Access::
* Source Location Printing::
* Compiler Policy Control::
* Exiting Commands::
* Information Commands::
* Breakpoint Commands::
* Function Tracing::
* Specials::
File: cmu-user.info Node: Debugger Introduction, Prev: The Debugger, Up: The Debugger, Next: The Command Loop
Debugger Introduction
=====================
The CMU Common Lisp debugger is unique in its level of support for source-level
debugging of compiled code. Although some other debuggers allow access of
variables by name, this seems to be the first Common Lisp debugger that:
* Tells you when a variable doesn't have a value because it hasn't been
initialized yet or has already been deallocated, or
* Can display the precise source location corresponding to a code
location in the debugged program.
These features allow the debugging of compiled code to be made almost
indistinguishable from interpreted code debugging.
The debugger is an interactive command loop that allows a user to examine
the function call stack. The debugger is invoked when:
* A serious-condition is signalled, and it is not handled, or
* error is called, and the condition it signals is not handled, or
* The debugger is explicitly invoked with the CMU Common Lisp break
or debug functions.
When you enter the debugger, it looks something like this:
Error in function CAR. Wrong type argument, 3, should have been of
type LIST.
Restarts:
0: Return to Top-Level.
Debug (type H for help)
(CAR 3)
0]
The first group of lines describe what the error was that put us in the
debugger. In this case `car' was called on `3'. After `Restarts:' is a
list of all the ways that we can restart execution after this error. In
this case, the only option is to return to top-level. After printing
its banner, the debugger prints the current frame and the debugger
prompt.
File: cmu-user.info Node: The Command Loop, Prev: Debugger Introduction, Up: The Debugger, Next: Stack Frames
The Command Loop
================
The debugger is an interactive read-eval-print loop much like the normal
top-level, but some symbols are interpreted as debugger commands instead
of being evaluated. A debugger command starts with the symbol name of
the command, possibly followed by some arguments on the same line. Some
commands prompt for additional input. Debugger commands can be
abbreviated by any unambiguous prefix: `help' can be typed as `h', `he',
etc. For convenience, some commands have ambiguous one-letter
abbreviations: `f' for `frame'.
The package is not significant in debugger commands; any symbol with the
name of a debugger command will work. If you want to show the value of
a variable that happens also to be the name of a debugger command, you
can use the `list-locals' command or the `debug:var' function, or you
can wrap the variable in a `progn' to hide it from the command loop.
The debugger prompt is "FRAME`]'", where FRAME is the number of the
current frame. Frames are numbered starting from zero at the top (most
recent call), increasing down to the bottom. The current frame is the
frame that commands refer to. The current frame also provides the
lexical environment for evaluation of non-command forms.
environment of the functions being debugged. The debugger can only
access variables. You can't `go' or `return-from' into a function, and
you can't call local functions. Special variable references are
evaluated with their current value (the innermost binding around the
debugger invocation) -- you don't get the value that the special had in
the current frame. ? for more information on debugger variable access.
File: cmu-user.info Node: Stack Frames, Prev: The Command Loop, Up: The Debugger, Next: Variable Access
Stack Frames
============
A stack frame is the run-time representation of a call to a function;
the frame stores the state that a function needs to remember what it is
doing. Frames have:
* Variables (?), which are the values being operated
on, and
* Arguments to the call (which are really just particularly interesting
variables), and
* A current location (?), which is the place in the program where the
function was running when it stopped to call another function, or
because of an interrupt or error.
* Menu:
* Stack Motion::
* How Arguments are Printed::
* Function Names::
* Funny Frames::
* Debug Tail Recursion::
* Unknown Locations and Interrupts::
File: cmu-user.info Node: Stack Motion, Prev: Stack Frames, Up: Stack Frames, Next: How Arguments are Printed
Stack Motion
------------
These commands move to a new stack frame and print the name of the function
and the values of its arguments in the style of a Lisp function call:
`up'
Move up to the next higher frame. More recent function calls are
considered to be higher on the stack.
`down'
Move down to the next lower frame.
`top'
Move to the highest frame.
`bottom'
Move to the lowest frame.
`frame' [N]
Move to the frame with the specified number. Prompts for the
number if not supplied.
File: cmu-user.info Node: How Arguments are Printed, Prev: Stack Motion, Up: Stack Frames, Next: Function Names
How Arguments are Printed
-------------------------
A frame is printed to look like a function call, but with the actual argument
values in the argument positions. So the frame for this call in the source:
(myfun (+ 3 4) 'a)
would look like this:
(MYFUN 7 A)
All keyword and optional arguments are displayed with their actual
values; if the corresponding argument was not supplied, the value will
be the default. So this call:
(subseq "foo" 1)
would look like this:
(SUBSEQ "foo" 1 3)
And this call:
(string-upcase "test case")
would look like this:
(STRING-UPCASE "test case" :START 0 :END NIL)
The arguments to a function call are displayed by accessing the argument
variables. Although those variables are initialized to the actual
argument values, they can be set inside the function; in this case the
new value will be displayed.
`&rest' arguments are handled somewhat differently. The value of
the rest argument variable is displayed as the spread-out arguments to
the call, so:
(format t "~A is a ~A." "This" 'test)
would look like this:
(FORMAT T "~A is a ~A." "This" 'TEST)
Rest arguments cause an exception to the normal display of keyword
arguments in functions that have both `&rest' and `&key' arguments. In
this case, the keyword argument variables are not displayed at all; the
rest arg is displayed instead. So for these functions, only the
keywords actually supplied will be shown, and the values displayed will
be the argument values, not values of the (possibly modified) variables.
If the variable for an argument is never referenced by the function, it
will be deleted. The variable value is then unavailable, so the
debugger prints `<unused-arg>' instead of the value. Similarly, if for
any of a number of reasons (described in more detail in section ?) the
value of the variable is unavailable or not known to be available, then
`<unavailable-arg>' will be printed instead of the argument value.
Printing of argument values is controlled by `*debug-print-level*' and
debug-print-length ?.
File: cmu-user.info Node: Function Names, Prev: How Arguments are Printed, Up: Stack Frames, Next: Funny Frames
Function Names
--------------
If a function is defined by `defun', `labels', or `flet', then the
debugger will print the actual function name after the open parenthesis, like:
(STRING-UPCASE "test case" :START 0 :END NIL)
((SETF AREF) #\a "for" 1)
Otherwise, the function name is a string, and will be printed in quotes:
("DEFUN MYFUN" BAR)
("DEFMACRO DO" (DO ((I 0 (1+ I))) ((= I 13))) NIL)
("SETQ *GC-NOTIFY-BEFORE*")
This string name is derived from the `def'MUMBLE form that encloses or
expanded into the lambda, or the outermost enclosing form if there is no
`def'MUMBLE.
File: cmu-user.info Node: Funny Frames, Prev: Function Names, Up: Stack Frames, Next: Debug Tail Recursion
Funny Frames
------------
Sometimes the evaluator introduces new functions that are used to
implement a user function, but are not directly specified in the source.
The main place this is done is for checking argument type and syntax.
Usually these functions do their thing and then go away, and thus are
not seen on the stack in the debugger. But when you get some sort of
error during lambda-list processing, you end up in the debugger on one
of these funny frames.
These funny frames are flagged by printing "`['KEYWORD`]'" after the
parentheses. For example, this call:
(car 'a 'b)
will look like this:
(CAR 2 A) [:EXTERNAL]
And this call:
(string-upcase "test case" :end)
would look like this:
("DEFUN STRING-UPCASE" "test case" 335544424 1) [:OPTIONAL]
As you can see, these frames have only a vague resemblance to the original
call. Fortunately, the error message displayed when you enter the debugger
will usually tell you what problem is (in these cases, too many arguments
and odd keyword arguments.) Also, if you go down the stack to the frame for
the calling function, you can display the original source (?.)
With recursive or block compiled functions (?), an `:EXTERNAL' frame may
appear before the frame representing the first call to the recursive
function or entry to the compiled block. This is a consequence of the
way the compiler does block compilation: there is nothing odd with your
program. You will also see `:CLEANUP' frames during the execution of
`unwind-protect' cleanup code. Note that inline expansion and
open-coding affect what frames are present in the debugger, see sections
? and ?.
File: cmu-user.info Node: Debug Tail Recursion, Prev: Funny Frames, Up: Stack Frames, Next: Unknown Locations and Interrupts
Debug Tail Recursion
--------------------
Both the compiler and the interpreter are "properly tail recursive." If a
function call is in a tail-recursive position, the stack frame will be
deallocated at the time of the call, rather than after the call returns.
Consider this backtrace:
(BAR ...)
(FOO ...)
Because of tail recursion, it is not necessarily the case that
`FOO' directly called `BAR'. It may be that `FOO' called
some other function `FOO2' which then called `BAR'
tail-recursively, as in this example:
(defun foo ()
...
(foo2 ...)
...)
(defun foo2 (...)
...
(bar ...))
(defun bar (...)
...)
Usually the elimination of tail-recursive frames makes debugging more
pleasant, since theses frames are mostly uninformative. If there is any
doubt about how one function called another, it can usually be
eliminated by finding the source location in the calling frame (section
?.)
For a more thorough discussion of tail recursion, ?.
File: cmu-user.info Node: Unknown Locations and Interrupts, Prev: Debug Tail Recursion, Up: Stack Frames
Unknown Locations and Interrupts
--------------------------------
The debugger operates using special debugging information attached to
the compiled code. This debug information tells the debugger what it
needs to know about the locations in the code where the debugger can be
invoked. If the debugger somehow encounters a location not described in
the debug information, then it is said to be UNKNOWN. If the code
location for a frame is unknown, then some variables may be
inaccessible, and the source location cannot be precisely displayed.
There are three reasons why a code location could be unknown:
* There is inadequate debug information due to the value of the
`debug' optimization quality. ?.
* The debugger was entered because of an interrupt such as `^C'.
* A hardware error such as "`bus error'" occurred in code that was
compiled unsafely due to the value of the `safety' optimization
quality. ?.
In the last two cases, the values of argument variables are accessible,
but may be incorrect. ? for more details on when variable values are
accessible.
It is possible for an interrupt to happen when a function call or return
is in progress. The debugger may then flame out with some obscure error
or insist that the bottom of the stack has been reached, when the real
problem is that the current stack frame can't be located. If this
happens, return from the interrupt and try again.
When running interpreted code, all locations should be known. However,
an interrupt might catch some subfunction of the interpreter at an
unknown location. In this case, you should be able to go up the stack a
frame or two and reach an interpreted frame which can be debugged.
File: cmu-user.info Node: Variable Access, Prev: Stack Frames, Up: The Debugger, Next: Source Location Printing
Variable Access
===============
There are three ways to access the current frame's local variables in
the debugger. The simplest is to type the variable's name into the
debugger's read-eval-print loop. The debugger will evaluate the
variable reference as though it had appeared inside that frame.
The debugger doesn't really understand lexical scoping; it has just one
namespace for all the variables in a function. If a symbol is the name
of multiple variables in the same function, then the reference appears
ambiguous, even though lexical scoping specifies which value is visible
at any given source location. If the scopes of the two variables are
not nested, then the debugger can resolve the ambiguity by observing
that only one variable is accessible.
When there are ambiguous variables, the evaluator assigns each one a
small integer identifier. The `debug:var' function and the
`list-locals' command use this identifier to distinguish between
ambiguous variables:
`list-locals' [PREFIX]
This command prints the name and value of all variables in the
current frame whose name has the specified PREFIX. PREFIX may be a
string or a symbol. If no PREFIX is given, then all available
variables are printed. If a variable has a potentially ambiguous
name, then the name is printed with a "`#'IDENTIFIER" suffix, where
IDENTIFIER is the small integer used to make the name unique.
-- Function: var NAME &optional IDENTIFIER
This function returns the value of the variable in the current
frame with the specified NAME. If supplied, IDENTIFIER determines
which value to return when there are ambiguous variables.
When NAME is a symbol, it is interpreted as the symbol name of the
variable, i.e. the package is significant. If NAME is an
uninterned symbol (gensym), then return the value of the uninterned
variable with the same name. If NAME is a string, `debug:var'
interprets it as the prefix of a variable name, and must
unambiguously complete to the name of a valid variable.
This function is useful mainly for accessing the value of
uninterned or ambiguous variables, since most variables can be
evaluated directly.
* Menu:
* Variable Value Availability::
* Note On Lexical Variable Access::
File: cmu-user.info Node: Variable Value Availability, Prev: Variable Access, Up: Variable Access, Next: Note On Lexical Variable Access
Variable Value Availability
---------------------------
The value of a variable may be unavailable to the debugger in portions
of the program where CMU Common Lisp says that the variable is defined.
If a variable value is not available, the debugger will not let you read
or write that variable. With one exception, the debugger will never
display an incorrect value for a variable. Rather than displaying
incorrect values, the debugger tells you the value is unavailable.
The one exception is this: if you interrupt (e.g., with `^C') or if
there is an unexpected hardware error such as "`bus error'" (which
should only happen in unsafe code), then the values displayed for
arguments to the interrupted frame might be incorrect. (1) (*Note
Variable Value Availability-Footnotes::) This exception applies only to
the interrupted frame: any frame farther down the stack will be fine.
The value of a variable may be unavailable for these reasons:
* The value of the `debug' optimization quality may have omitted
debug information needed to determine whether the variable is
available. Unless a variable is an argument, its value will only
be available when `debug' is at least `2'.
* The compiler did lifetime analysis and determined that the value
was no longer needed, even though its scope had not been exited.
Lifetime analysis is inhibited when the `debug' optimization
quality is `3'.
* The variable's name is an uninterned symbol (gensym). To save
space, the compiler only dumps debug information about uninterned
variables when the `debug' optimization quality is `3'.
* The frame's location is unknown (*Note Unknown Locations and
Interrupts::) because the debugger was entered due to an interrupt
or unexpected hardware error. Under these conditions the values of
arguments will be available, but might be incorrect. This is the
exception above.
* The variable was optimized out of existence. Variables with no
reads are always optimized away, even in the interpreter. The
degree to which the compiler deletes variables will depend on the
value of the `compile-speed' optimization quality, but most
source-level optimizations are done under all compilation policies.
Since it is especially useful to be able to get the arguments to a
function, argument variables are treated specially when the `speed'
optimization quality is less than `3' and the `debug' quality is at
least `1'. With this compilation policy, the values of argument
variables are almost always available everywhere in the function, even
at unknown locations. For non-argument variables, `debug' must be at
least `2' for values to be available, and even then, values are only
available at known locations.
File: cmu-user.info Node: Variable Value Availability-Footnotes, Up: Variable Value Availability
(1) Since the location of an interrupt or hardware error will always be
an unknown location (*Note Unknown Locations and Interrupts::), non-argument variable
values will never be available in the interrupted frame.
File: cmu-user.info Node: Note On Lexical Variable Access, Prev: Variable Value Availability, Up: Variable Access
Note On Lexical Variable Access
-------------------------------
When the debugger command loop establishes variable bindings for
available variables, these variable bindings have lexical scope and
dynamic extent. (2) (*Note Note On Lexical Variable Access-Footnotes::)
You can close over them, but such closures can't be used as upward
funargs.
You can also set local variables using `setq', but if the variable was
closed over in the original source and never set, then setting the
variable in the debugger may not change the value in all the functions
the variable is defined in. Another risk of setting variables is that
you may assign a value of a type that the compiler proved the variable
could never take on. This may result in bad things happening.
File: cmu-user.info Node: Note On Lexical Variable Access-Footnotes, Up: Note On Lexical Variable Access
(2) The variable bindings are actually created using the CMU Common Lisp
`symbol-macro-let' special form.
File: cmu-user.info Node: Source Location Printing, Prev: Variable Access, Up: The Debugger, Next: Compiler Policy Control
Source Location Printing
========================
One of CMU CMU Common Lisp's unique capabilities is source level debugging of compiled
code. These commands display the source location for the current frame:
`source' [CONTEXT]
This command displays the file that the current frame's function
was defined from (if it was defined from a file), and then the
source form responsible for generating the code that the current
frame was executing. If CONTEXT is specified, then it is an
integer specifying the number of enclosing levels of list structure
to print.
`vsource' [CONTEXT]
This command is identical to `source', except that it uses the
global values of `*print-level*' and `*print-length*' instead of
the debugger printing control variables `*debug-print-level*' and
`*debug-print-length*'.
The source form for a location in the code is the innermost list present
in the original source that encloses the form responsible for generating
that code. If the actual source form is not a list, then some enclosing
list will be printed. For example, if the source form was a reference
to the variable `*some-random-special*', then the innermost
enclosing evaluated form will be printed. Here are some possible
enclosing forms:
(let ((a *some-random-special*))
...)
(+ *some-random-special* ...)
If the code at a location was generated from the expansion of a macro or a
source-level compiler optimization, then the form in the original source that
expanded into that code will be printed. Suppose the file
`/usr/me/mystuff.lisp' looked like this:
(defmacro mymac ()
'(myfun))
(defun foo ()
(mymac)
...)
If `foo' has called `myfun', and is waiting for it to return, then the
`source' command would print:
; File: /usr/me/mystuff.lisp
(MYMAC)
Note that the macro use was printed, not the actual function call form,
`(myfun)'.
If enclosing source is printed by giving an argument to `source' or
`vsource', then the actual source form is marked by wrapping it in a list
whose first element is `#:***HERE***'. In the previous example,
`source 1' would print:
; File: /usr/me/mystuff.lisp
(DEFUN FOO ()
(#:***HERE***
(MYMAC))
...)
* Menu:
* How the Source is Found::
* Source Location Availability::
File: cmu-user.info Node: How the Source is Found, Prev: Source Location Printing, Up: Source Location Printing, Next: Source Location Availability
How the Source is Found
-----------------------
If the code was defined from Common Lisp by `compile' or `eval', then
the source can always be reliably located. If the code was defined from
a `fasl' file created by compile-file, then the debugger gets the source
forms it prints by reading them from the original source file. This is
a potential problem, since the source file might have moved or changed
since the time it was compiled.
The source file is opened using the `truename' of the source file
pathname originally given to the compiler. This is an absolute pathname
with all logical names and symbolic links expanded. If the file can't
be located using this name, then the debugger gives up and signals an
error.
If the source file can be found, but has been modified since the time it was
compiled, the debugger prints this warning:
; File has been modified since compilation: ; FILENAME ; Using form
offset instead of character position.
where FILENAME is the name of the source file. It then proceeds using a
robust but not foolproof heuristic for locating the source. This heuristic
works if:
* No top-level forms before the top-level form containing the source have been
added or deleted, and
* The top-level form containing the source has not been modified much. (More
precisely, none of the list forms beginning before the source form have been
added or deleted.)
If the heuristic doesn't work, the displayed source will be wrong, but
will probably be near the actual source. If the "shape" of the
top-level form in the source file is too different from the original
form, then an error will be signalled. When the heuristic is used, the
the source location commands are noticeably slowed.
Source location printing can also be confused if (after the source was
compiled) a read-macro you used in the code was redefined to expand into
something different, or if a read-macro ever returns the same `eq' list
twice. If you don't define read macros and don't use `##' in perverted
ways, you don't need to worry about this.
File: cmu-user.info Node: Source Location Availability, Prev: How the Source is Found, Up: Source Location Printing
Source Location Availability
----------------------------
Source location information is only available when the `debug'
optimization quality is at least `2'. If source location information is
unavailable, the source commands will give an error message.
If source location information is available, but the source location is
unknown because of an interrupt or unexpected hardware error
(*Note Unknown Locations and Interrupts::), then the command will print:
Unknown location: using block start.
and then proceed to print the source location for the start of the basic
block enclosing the code location. It's a bit complicated to explain exactly what a basic block is, but
here are some properties of the block start location:
* The block start location may be the same as the true location.
* The block start location will never be later in the the program's
flow of control than the true location.
* No conditional control structures (such as `if', `cond', `or') will
intervene between the block start and the true location (but note
that some conditionals present in the original source could be
optimized away.) Function calls do not end basic blocks.
* The head of a loop will be the start of a block.
* The programming language concept of "block structure" and the CMU
Common Lisp `block' special form are totally unrelated to the
compiler's basic block.
In other words, the true location lies between the printed location and the
next conditional (but watch out because the compiler may have changed the
program on you.)
File: cmu-user.info Node: Compiler Policy Control, Prev: Source Location Printing, Up: The Debugger, Next: Exiting Commands
Compiler Policy Control
=======================
The compilation policy specified by `optimize' declarations affects the
behavior seen in the debugger. The `debug' quality directly affects the
debugger by controlling the amount of debugger information dumped.
Other optimization qualities have indirect but observable effects due to
changes in the way compilation is done.
Unlike the other optimization qualities (which are compared in relative value
to evaluate tradeoffs), the `debug' optimization quality is directly
translated to a level of debug information. This absolute interpretation
allows the user to count on a particular amount of debug information being
available even when the values of the other qualities are changed during
compilation. These are the levels of debug information that correspond to the
values of the `debug' quality:
`0'
Only the function name and enough information to allow the stack to
be parsed.
`> 0'
Any level greater than `0' gives level `0' plus all argument
variables. Values will only be accessible if the argument variable
is never set and `speed' is not `3'. CMU Common Lisp allows any
real value for optimization qualities. It may be useful to specify
`0.5' to get backtrace argument display without argument
documentation.
`1'
Level `1' provides argument documentation (printed arglists) and
derived argument/result type information. This makes describe more
informative, and allows the compiler to do compile-time argument
count and type checking for any calls compiled at run-time.
`2'
Level `1' plus all interned local variables, source location
information, and lifetime information that tells the debugger when
arguments are available (even when `speed' is `3' or the argument
is set.) This is the default.
`3'
Level `2' plus all uninterned variables. In addition, lifetime
analysis is disabled (even when `speed' is `3'), ensuring that all
variable values are available at any known location within the
scope of the binding. This has a speed penalty in addition to the
obvious space penalty.
As you can see, if the `speed' quality is `3', debugger performance is
degraded. This effect comes from the elimination of argument variable
special-casing (*Note Variable Value Availability::.) Some degree of
speed/debuggability tradeoff is unavoidable, but the effect is not too
drastic when `debug' is at least `2'.
In addition to `inline' and `notinline' declarations, the relative
values of the `speed' and `space' qualities also change whether
functions are inline expanded (?.) If a function is inline expanded,
then there will be no frame to represent the call, and the arguments
will be treated like any other local variable. Functions may also be
"semi-inline", in which case there is a frame to represent the call, but
the call is to an optimized local version of the function, not to the
original function.